home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / comm / tcp / AmigaTCP.lha / AmigaTCP / src / tcpin.c < prev    next >
C/C++ Source or Header  |  1989-06-24  |  22KB  |  823 lines

  1. /* Process incoming TCP segments. Page number references are to ARPA RFC-793,
  2.  * the TCP specification.
  3.  */
  4.  
  5. #include "machdep.h"
  6. #include "timer.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "internet.h"
  10. #include "tcp.h"
  11. #include "icmp.h"
  12. #include "ip.h"
  13.  
  14. struct tcp_stat tcp_stat;
  15.  
  16. /* This function is called from IP with the IP header in machine byte order,
  17.  * along with a mbuf chain pointing to the TCP header.
  18.  */
  19. void
  20. tcp_input(bp,protocol,source,dest,tos,length,rxbroadcast)
  21. struct mbuf *bp;    /* Data field, if any */
  22. char protocol;        /* Should always be TCP_PTCL */
  23. int32 source;        /* Remote IP address */
  24. int32 dest;        /* Our IP address */
  25. char tos;        /* Type of Service */
  26. int16 length;        /* Length of data field */
  27. char rxbroadcast;    /* Incoming broadcast - discard if true */
  28. {
  29.     void reset(),update();
  30.     void proc_syn(),send_syn(),add_reseq(),get_reseq();
  31.  
  32.     register struct tcb *tcb;    /* TCP Protocol control block */
  33.     struct tcp_header seg;        /* Local copy of segment header */
  34.     int16 mss;            /* Incoming MSS, if any */
  35.     struct connection conn;        /* Local copy of addresses */
  36.     struct pseudo_header ph;    /* Pseudo-header for checksumming */
  37.     int16 optlen;            /* Length of TCP options */
  38.  
  39.     if(bp == NULLBUF)
  40.         return;
  41.  
  42.     if(rxbroadcast){
  43.         /* Any TCP packet arriving as a broadcast is
  44.          * to be completely IGNORED!!
  45.          */
  46.         tcp_stat.bdcsts++;
  47.         free_p(bp);
  48.     }
  49.     ph.source = source;
  50.     ph.dest = dest;
  51.     ph.protocol = protocol;
  52.     ph.zero = 0;
  53.     ph.length = length;
  54.     if(cksum(&ph,bp,length) != 0){
  55.         /* Checksum failed, ignore segment completely */
  56.         tcp_stat.checksum++;
  57.         free_p(bp);
  58.         return;
  59.     }
  60.     /* Form local copy of TCP header in host byte order */
  61.     if(pullup(&bp,(char *)&seg,sizeof(struct tcp_header))
  62.          != sizeof(struct tcp_header)){
  63.         /* TCP header is too small */
  64.         tcp_stat.runt++;
  65.         free_p(bp);
  66.         return;
  67.     }
  68.     length -= sizeof(struct tcp_header);
  69.     seg.source = ntohs(seg.source);
  70.     seg.dest = ntohs(seg.dest);
  71.     seg.seq = ntohl(seg.seq);
  72.     seg.ack = ntohl(seg.ack);
  73.     seg.wnd = ntohs(seg.wnd);
  74.     seg.up = ntohs(seg.up);    /* Unused as of yet */
  75.  
  76.     /* Examine options, if any (there can only be MSS). */
  77.     optlen = hinibble(seg.offset) * sizeof(long) - sizeof(struct tcp_header);
  78.     if(optlen != 0){
  79.         struct mss *mssp;
  80.  
  81.         mssp = (struct mss *)bp->data;
  82.         if(mssp->kind == MSS_KIND && mssp->length == MSS_LENGTH){
  83.             mss = ntohs(mssp->mss);
  84.         }
  85.         pullup(&bp,NULLCHAR,optlen);
  86.         length -= optlen;
  87.     } else {
  88.         mss = 0;
  89.     }
  90.     /* Fill in connection structure and find TCB */
  91.     conn.local.address = dest;
  92.     conn.local.port = seg.dest;
  93.     conn.remote.address = source;
  94.     conn.remote.port = seg.source;
  95.     
  96.     if((tcb = lookup_tcb(&conn)) == NULLTCB){
  97.         struct tcb *ntcb;
  98.         char *malloc();
  99.         void link_tcb();
  100.  
  101.         /* Check that this segment carries a SYN, and that
  102.          * there's a LISTEN on this socket with
  103.          * unspecified source address and port
  104.          */
  105.         conn.remote.address = 0;
  106.         conn.remote.port = 0;
  107.         if(!(seg.flags & SYN) || (tcb = lookup_tcb(&conn)) == NULLTCB){
  108.             /* No unspecified LISTEN either, so reject */
  109.             free_p(bp);
  110.             reset(source,dest,tos,length,&seg);
  111.             return;
  112.         }
  113.         /* We've found an unspecified remote socket, so clone the TCB
  114.          * and stuff the foreign socket into the clone.
  115.          */
  116.         if((ntcb = (struct tcb *)malloc(sizeof (struct tcb))) == NULLTCB){
  117.             free_p(bp);
  118.             /* This may fail, but we should at least try */
  119.             reset(source,dest,tos,length,&seg);
  120.             return;
  121.         }
  122.         bcopy((char *)tcb,(char *)ntcb,sizeof(struct tcb));
  123.         tcb = ntcb;
  124.         tcb->conn.remote.address = source;
  125.         tcb->conn.remote.port = seg.source;
  126.         tcb->timer.arg = (int *)tcb;
  127.         link_tcb(tcb);
  128.     }
  129.     /* Do unsynchronized-state processing (p. 65-68) */
  130.     switch(tcb->state){
  131.     case CLOSED:
  132.         free_p(bp);
  133.         reset(source,dest,tos,length,&seg);
  134.         return;
  135.     case LISTEN:
  136.         if(seg.flags & RST){
  137.             free_p(bp);
  138.             return;
  139.         }
  140.         if(seg.flags & ACK){
  141.             free_p(bp);
  142.             reset(source,dest,tos,length,&seg);
  143.             return;
  144.         }
  145.         if(seg.flags & SYN){
  146.  
  147.             /* (Security check is bypassed) */
  148.             /* page 66 */
  149.             tcp_stat.conin++;
  150.             proc_syn(tcb,tos,&seg,mss);
  151.             send_syn(tcb);
  152.             setstate(tcb,SYN_RECEIVED);        
  153.             if(length != 0 || seg.flags & FIN) {
  154.                 break;        /* Continue processing if there's more */
  155.             }
  156.             tcp_output(tcb);
  157.         }
  158.         free_p(bp);    /* Unlikely to get here directly */
  159.         return;
  160.     case SYN_SENT:
  161.         if(seg.flags & ACK){
  162.             if(!seq_within(seg.ack,tcb->iss+1,tcb->snd.nxt)){
  163.                 free_p(bp);
  164.                 reset(source,dest,tos,length,&seg);
  165.                 return;
  166.             }
  167.         }
  168.         if(seg.flags & RST){    /* p 67 */
  169.             if(seg.flags & ACK){
  170.                 /* The ack must be acceptable since we just checked it.
  171.                  * This is how the remote side refuses connect requests.
  172.                  */
  173.                 close_self(tcb,RESET);
  174.             }
  175.             free_p(bp);
  176.             return;
  177.         }
  178.         /* (Security check skipped here) */
  179.         /* Check incoming precedence; it must match if there's an ACK */
  180.         if((seg.flags & ACK) && PREC(tos) != PREC(tcb->tos)){
  181.             free_p(bp);
  182.             reset(source,dest,tos,length,&seg);
  183.             return;
  184.         }
  185.         if(seg.flags & SYN){
  186.             proc_syn(tcb,tos,&seg,mss);
  187.             if(seg.flags & ACK){
  188.                 /* Our SYN has been acked, otherwise the ACK
  189.                  * wouldn't have been valid.
  190.                  */
  191.                 update(tcb,&seg);
  192.                 setstate(tcb,ESTABLISHED);
  193.             } else {
  194.                 setstate(tcb,SYN_RECEIVED);
  195.             }
  196.             if(length != 0 || (seg.flags & FIN)) {
  197.                 break;        /* Continue processing if there's more */
  198.             }
  199.             tcp_output(tcb);
  200.         } else {
  201.             free_p(bp);    /* Ignore if neither SYN or RST is set */
  202.         }
  203.         return;
  204.     }
  205.     /* We reach this point directly in any synchronized state. Note that
  206.      * if we fell through from LISTEN or SYN_SENT processing because of a
  207.      * data-bearing SYN, window trimming and sequence testing "cannot fail".
  208.      */
  209.  
  210.     /* Trim segment to fit receive window. */
  211.     if(trim(tcb,&seg,&bp,&length) == -1){
  212.         /* Segment is unacceptable */
  213.         if(!(seg.flags & RST)){
  214.             tcb->force = 1;
  215.             tcp_output(tcb);
  216.         }
  217.         return;
  218.     }
  219.     /* If segment isn't the next one expected, and there's data
  220.      * or flags associated with it, put it on the resequencing
  221.      * queue and return. Don't send anything in reply.
  222.      *
  223.      * Processing the ACK in an out-of-sequence segment without
  224.      * flags or data should be safe, however.
  225.      */
  226.     if(seg.seq != tcb->rcv.nxt
  227.      && (length != 0 || (seg.flags & (SYN|FIN)) )){
  228.         add_reseq(tcb,tos,&seg,bp,length);
  229.         return;
  230.     }
  231.     /* This loop first processes the current segment, and then
  232.      * repeats if it can process the resequencing queue.
  233.      */
  234.     for(;;){
  235.         /* We reach this point with an acceptable segment; all data and flags
  236.          * are in the window, and the starting sequence number equals rcv.nxt
  237.          * (p. 70)
  238.          */    
  239.         if(seg.flags & RST){
  240.             switch(tcb->state){
  241.             case SYN_RECEIVED:
  242.                 setstate(tcb,LISTEN);
  243.                 free_p(bp);
  244.                 return;
  245.             default:
  246.                 close_self(tcb,RESET);
  247.                 free_p(bp);
  248.                 return;
  249.             }
  250.         }
  251.         /* (Security check skipped here) p. 71 */
  252.         /* Check for precedence mismatch or erroneous extra SYN */
  253.         if(PREC(tos) != PREC(tcb->tos) || (seg.flags & SYN)){
  254.             free_p(bp);
  255.             reset(source,dest,tos,length,&seg);
  256.             return;
  257.         }
  258.         /* Check ack field p. 72 */
  259.         if(!(seg.flags & ACK)){
  260.             free_p(bp);    /* All segments after synchronization must have ACK */
  261.             return;
  262.         }
  263.         /* Process ACK */
  264.         switch(tcb->state){
  265.         case SYN_RECEIVED:
  266.             if(seq_within(seg.ack,tcb->snd.una+1,tcb->snd.nxt)){
  267.                 update(tcb,&seg);
  268.                 setstate(tcb,ESTABLISHED);
  269.             } else {
  270.                 free_p(bp);
  271.                 reset(source,dest,tos,length,&seg);
  272.                 return;
  273.             }
  274.             break;
  275.         case ESTABLISHED:
  276.         case CLOSE_WAIT:
  277.             update(tcb,&seg);
  278.             break;
  279.         case FINWAIT1:    /* p. 73 */
  280.             update(tcb,&seg);
  281.             if(tcb->sndcnt == 0){
  282.                 /* Our FIN is acknowledged */
  283.                 setstate(tcb,FINWAIT2);
  284.             }
  285.             break;
  286.         case FINWAIT2:
  287.             update(tcb,&seg);
  288.             break;
  289.         case CLOSING:
  290.             update(tcb,&seg);
  291.             if(tcb->sndcnt == 0){
  292.                 /* Our FIN is acknowledged */
  293.                 setstate(tcb,TIME_WAIT);
  294.                 tcb->timer.start = MSL2;
  295.                 start_timer(&tcb->timer);
  296.             }
  297.             break;
  298.         case LAST_ACK:
  299.             update(tcb,&seg);
  300.             if(tcb->sndcnt == 0){
  301.                 /* Our FIN is acknowledged, close connection */
  302.                 close_self(tcb,NORMAL);
  303.                 return;
  304.             }            
  305.         case TIME_WAIT:
  306.             tcb->force = 1;
  307.             start_timer(&tcb->timer);
  308.         }
  309.  
  310.         /* (URGent bit processing skipped here) */
  311.  
  312.         /* Process the segment text, if any, beginning at rcv.nxt (p. 74) */
  313.         if(length != 0){
  314.             switch(tcb->state){
  315.             case SYN_RECEIVED:
  316.             case ESTABLISHED:
  317.             case FINWAIT1:
  318.             case FINWAIT2:
  319.                 /* Place on receive queue */
  320.                 append(&tcb->rcvq,bp);
  321.                 tcb->rcvcnt += length;
  322.                 tcb->rcv.nxt += length;
  323.                 tcb->rcv.wnd -= length;
  324.                 tcb->force = 1;
  325.                 break;
  326.             default:
  327.                 /* Ignore segment text */
  328.                 free_p(bp);
  329.                 break;
  330.             }
  331.         }
  332.         /* If the user has set up a r_upcall function, AND
  333.          * the receive window is more than half full OR
  334.          * has the urg, push or fin flags set, notify him.
  335.          *
  336.          * All this is done before sending an acknowledgement,
  337.          * to give the user a chance to piggyback some reply data.
  338.          * It's also done before processing FIN so that the state
  339.          * change upcall will occur after the user has had a chance
  340.          * to read the last of the incoming data.
  341.          */
  342.         if(tcb->r_upcall){
  343.             if(tcb->rcvcnt >= tcb->rcv.wnd || (seg.flags & (FIN|URG|PSH))){
  344.                 (*tcb->r_upcall)(tcb,tcb->rcvcnt);
  345.             }
  346.         }
  347.         /* process FIN bit (p 75) */
  348.         if(seg.flags & FIN){
  349.             tcb->force = 1;    /* Always respond with an ACK */
  350.  
  351.             switch(tcb->state){
  352.             case SYN_RECEIVED:
  353.             case ESTABLISHED:
  354.                 tcb->rcv.nxt++;
  355.                 setstate(tcb,CLOSE_WAIT);
  356.                 break;
  357.             case FINWAIT1:
  358.                 tcb->rcv.nxt++;
  359.                 if(tcb->sndcnt == 0){
  360.                     /* Our FIN has been acked; bypass CLOSING state */
  361.                     setstate(tcb,TIME_WAIT);
  362.                     tcb->timer.start = MSL2;
  363.                     start_timer(&tcb->timer);
  364.                 } else {
  365.                     setstate(tcb,CLOSING);
  366.                 }
  367.                 break;
  368.             case FINWAIT2:
  369.                 tcb->rcv.nxt++;
  370.                 setstate(tcb,TIME_WAIT);
  371.                 tcb->timer.start = MSL2;
  372.                 start_timer(&tcb->timer);
  373.                 break;
  374.             case CLOSE_WAIT:
  375.             case CLOSING:
  376.             case LAST_ACK:
  377.                 break;        /* Ignore */
  378.             case TIME_WAIT:    /* p 76 */
  379.                 start_timer(&tcb->timer);
  380.                 break;
  381.             }
  382.         }
  383.         /* Scan the resequencing queue, looking for a segment we can handle,
  384.          * and freeing all those that are now obsolete.
  385.          */
  386.         while(tcb->reseq != NULLRESEQ && seq_ge(tcb->rcv.nxt,tcb->reseq->seg.seq)){
  387.             get_reseq(tcb,&tos,&seg,&bp,&length);
  388.             if(trim(tcb,&seg,&bp,&length) == 0)
  389.                 goto gotone;
  390.             /* Segment is an old one; trim has freed it */
  391.         }
  392.         break;
  393. gotone:    ;
  394.     }
  395.     tcp_output(tcb);    /* Send any necessary ack */
  396. }
  397.  
  398. /* Process an incoming ICMP response */
  399. tcp_icmp(source,dest,type,code,data)
  400. int32 source;    /* Original IP datagram source (i.e. us) */
  401. int32 dest;    /* Original IP datagram dest (i.e., them) */
  402. char type,code;    /* ICMP error codes */
  403. char *data;    /* First 8 bytes of TCP header */
  404. {
  405.     struct tcp_header *tcph;
  406.     struct connection conn;
  407.     register struct tcb *tcb;
  408.  
  409.     /* Extract the socket info from the returned TCP header fragment
  410.      * Note that since this is a datagram we sent, the source fields
  411.      * refer to the local side.
  412.      */
  413.     tcph = (struct tcp_header *)data;
  414.     conn.local.address = source;
  415.     conn.local.port = ntohs(tcph->source);
  416.     conn.remote.address = dest;
  417.     conn.remote.port = ntohs(tcph->dest);
  418.     if((tcb = lookup_tcb(&conn)) == NULLTCB)
  419.         return;    /* Unknown connection, ignore */
  420.  
  421.     /* Verify that the sequence number in the returned segment corresponds
  422.      * to something currently unacknowledged. If not, it can safely
  423.      * be ignored.
  424.      */
  425.     if(!seq_within(ntohl(tcph->seq),tcb->snd.una,tcb->snd.nxt))
  426.         return;
  427.  
  428.     /* The strategy here is that Destination Unreachable and Time Exceeded
  429.      * messages that occur after a connection has been established are likely
  430.      * to be transient events, and shouldn't kill our connection (at least
  431.      * until after we've tried a few more times). On the other hand, if
  432.      * they occur on our very first attempt to send a datagram on a new
  433.      * connection, they're probably "for real". In any event, the info
  434.      * is saved.
  435.      */
  436.     switch(type){
  437.     case DEST_UNREACH:
  438.     case TIME_EXCEED:
  439.         tcb->type = type;
  440.         tcb->code = code;
  441.         if(tcb->state == SYN_SENT || tcb->state == SYN_RECEIVED){
  442.             close_self(tcb,NETWORK);
  443.         }
  444.         break;
  445.     case QUENCH:
  446.         break;        /* I really ought to implement this */
  447.     }
  448. }
  449.  
  450. /* Send an acceptable reset (RST) response for this segment */
  451. static void
  452. reset(source,dest,tos,length,seg)
  453. int32 source;    /* Remote IP address */
  454. int32 dest;        /* Our IP address */
  455. char tos;        /* Type of Service */
  456. int16 length;    /* Length of data portion */
  457. register struct tcp_header *seg;    /* Offending TCP header */
  458. {
  459.     struct mbuf *hbp;
  460.     struct pseudo_header ph;
  461.     register struct tcp_header *tcph;
  462.  
  463.     if(seg->flags & RST)
  464.         return;    /* Never send an RST in response to an RST */
  465.  
  466.     tcp_stat.resets++;
  467.     /* Compose the RST IP pseudo-header, swapping addresses */
  468.     ph.source = dest;
  469.     ph.dest = source;
  470.     ph.protocol = TCP_PTCL;
  471.     ph.zero = 0;
  472.     ph.length = sizeof(struct tcp_header);
  473.  
  474.     /* Allocate mbuf for the RST TCP header and fill it in */
  475.     if((hbp = alloc_mbuf(ph.length)) == NULLBUF)
  476.         return;    /* Can't do nothin' */
  477.  
  478.     hbp->cnt = ph.length;
  479.     tcph = (struct tcp_header *)hbp->data;
  480.  
  481.     tcph->source = htons(seg->dest);
  482.     tcph->dest = htons(seg->source);
  483.     tcph->flags = RST;
  484.  
  485.     if(seg->flags & ACK){
  486.         /* This reset is being sent to clear a half-open connection.
  487.          * Set the sequence number of the RST to the incoming ACK
  488.          * so it will be acceptable.
  489.          */
  490.         tcph->seq = htonl(seg->ack);
  491.         tcph->ack = 0;
  492.     } else {
  493.         /* We're rejecting a connect request (SYN) from LISTEN state
  494.          * so we have to "acknowledge" their SYN.
  495.          */
  496.         tcph->seq = 0;
  497.         if(seg->flags & SYN)
  498.             length++;
  499.         if(seg->flags & FIN)
  500.             length++;
  501.         tcph->ack = htonl((int32)(seg->seq + length));
  502.         tcph->flags |= ACK;
  503.     }
  504.     tcph->offset = (ph.length/sizeof(long)) << DSHIFT;
  505.     tcph->wnd = 0;
  506.     tcph->checksum = 0;
  507.     tcph->up = 0;
  508.     tcph->checksum = cksum(&ph,hbp,ph.length);
  509.     /* Ship it out (note swap of addresses) */
  510.     ip_send(dest,source,TCP_PTCL,tos,0,hbp,ph.length,0,0);
  511. }
  512.  
  513. /* Process an incoming acknowledgement and window indication.
  514.  * From page 72.
  515.  */
  516. static void
  517. update(tcb,seg)
  518. register struct tcb *tcb;
  519. register struct tcp_header *seg;
  520. {
  521.     int16 acked;
  522.     int32 rtt;
  523.  
  524.     acked = 0;
  525.     if(seq_gt(seg->ack,tcb->snd.nxt)){
  526.         tcb->force = 1;    /* Acks something not yet sent */
  527.         return;
  528.     }
  529.     /* Round trip time estimation */
  530.     if(seq_gt(tcb->rttseq,tcb->snd.una)){
  531.         /* A sequence number is actively being timed */
  532.         if(tcb->retry == 0 && seq_ge(seg->ack,tcb->rttseq)){
  533.             /* This packet was sent only once and now
  534.              * it's been acked, so compute the new smoothed
  535.              * estimate. The RT time is just the current time
  536.              * on the retransmission timer.
  537.              */
  538.             rtt = tcb->timer.start - tcb->timer.count;
  539.             rtt *= MSPTICK;    /* convert to ticks */
  540.             /* Fast attack/slow decay algorithm by Dave Mills
  541.              * (see RFC-889)
  542.              */
  543.             if(rtt > tcb->srtt){
  544.                 /* RTT is increasing, use fast attack */
  545.                 tcb->srtt = (ALPHA1*tcb->srtt + rtt)/(ALPHA1+1);
  546.             } else {
  547.                 /* RTT is decreasing, use slow decay */
  548.                 tcb->srtt = (ALPHA2*tcb->srtt + rtt)/(ALPHA2+1);
  549.             }
  550.             /* Set new retransmission timeout */
  551.             tcb->timer.start = (BETA * tcb->srtt)/MSPTICK;
  552.         }
  553.     }
  554.     /* If the remote window is closed, reset the retry counter even if
  555.      * this packet doesn't acknowledge anything new as long as the ACK
  556.      * is current.
  557.      * This allows closed-window probes to go on indefinitely.
  558.      */
  559.     if(seg->wnd == 0 && seq_ge(seg->ack,tcb->snd.una))
  560.         tcb->retry = 0;
  561.  
  562.     /* See if anything new is being acknowledged */
  563.     if(seq_gt(seg->ack,tcb->snd.una)){
  564.         acked = seg->ack - tcb->snd.una;
  565.         /* If we're waiting for an ack of our SYN, process it */
  566.         switch(tcb->state){
  567.         case SYN_SENT:
  568.         case SYN_RECEIVED:
  569.             acked--;
  570.             tcb->sndcnt--;
  571.         }
  572.         /* Remove acknowledged bytes from the send queue and update the
  573.          * unacknowledged pointer. If a FIN is being acked,
  574.          * pullup won't be able to remove it from the queue.
  575.          */
  576.         pullup(&tcb->sndq,NULLCHAR,acked);
  577.  
  578.         /* This will include the FIN if there is one */
  579.         tcb->sndcnt -= acked;
  580.         tcb->snd.una = seg->ack;
  581.  
  582.         /* If retransmissions have been occurring, make sure the
  583.          * send pointer doesn't repeat ancient history
  584.          */
  585.         if(seq_lt(tcb->snd.ptr,tcb->snd.una))
  586.             tcb->snd.ptr = tcb->snd.una;
  587.  
  588.         /* Reset the retry counter */
  589.         tcb->retry = 0;
  590.         /* Stop retransmission timer, but restart it if there is still
  591.          * unacknowledged data
  592.          */    
  593.         stop_timer(&tcb->timer);
  594.         if(tcb->snd.una != tcb->snd.nxt){
  595.             start_timer(&tcb->timer);
  596.         }
  597.     }
  598.     /* Decide if we need to do a window update.
  599.      * This is always checked whenever a legal ACK is received,
  600.      * because it might be a spontaneous window reopening.
  601.      */
  602.     if(seq_gt(seg->seq,tcb->snd.wl1) || ((seg->seq == tcb->snd.wl1) 
  603.      && seq_ge(seg->ack,tcb->snd.wl2))){
  604.         /* If the window had been closed, crank back the
  605.          * send pointer so we'll immediately resume transmission.
  606.          * Otherwise we'd have to wait until the next probe.
  607.          */
  608.         if(tcb->snd.wnd == 0 && seg->wnd != 0)
  609.             tcb->snd.ptr = tcb->snd.una;
  610.         tcb->snd.wnd = seg->wnd;
  611.         tcb->snd.wl1 = seg->seq;
  612.         tcb->snd.wl2 = seg->ack;
  613.     }
  614.     /* If outgoing data was acked, notify the user so he can send more
  615.      * unless we've already sent a FIN.
  616.      */
  617.     if(acked != 0 && tcb->t_upcall){
  618.         switch(tcb->state){
  619.          case ESTABLISHED:
  620.         case CLOSE_WAIT:
  621.             (*tcb->t_upcall)(tcb,tcb->window - tcb->sndcnt);
  622.         }
  623.     }
  624. }
  625.  
  626. /* Determine if the given sequence number is in our receiver window.
  627.  * NB: must not be used when window is closed!
  628.  */
  629. static
  630. int
  631. in_window(tcb,seq)
  632. struct tcb *tcb;
  633. int32 seq;
  634. {
  635.     return seq_within(seq,tcb->rcv.nxt,(int32)(tcb->rcv.nxt+tcb->rcv.wnd-1));
  636. }
  637.  
  638. /* Process an incoming SYN */
  639. static void
  640. proc_syn(tcb,tos,seg,mss)
  641. register struct tcb *tcb;
  642. char tos;
  643. struct tcp_header *seg;
  644. int16 mss;
  645. {
  646.     int16 mtu,ip_mtu();
  647.  
  648.     tcb->force = 1;    /* Always send a response */
  649.  
  650.     /* Note: It's not specified in RFC 793, but SND.WL1 and
  651.      * SND.WND are initialized here since it's possible for the
  652.      * window update routine in update() to fail depending on the
  653.      * IRS if they are left unitialized.
  654.      */
  655.     /* Check incoming precedence and increase if higher */
  656.     if(PREC(tos) > PREC(tcb->tos))
  657.         tcb->tos = tos;
  658.     tcb->rcv.nxt = seg->seq + 1;    /* p 68 */
  659.     tcb->snd.wl1 = tcb->irs = seg->seq;
  660.     tcb->snd.wnd = seg->wnd;
  661.     if(mss != 0)
  662.         tcb->mss = mss;
  663.     /* Check the MTU of the interface we'll use to reach this guy
  664.      * and lower the MSS so that unnecessary fragmentation won't occur
  665.      */
  666.     if((mtu = ip_mtu(tcb->conn.remote.address)) != 0){
  667.         /* Allow space for the TCP and IP headers */
  668.         mtu -= sizeof(struct tcp_header) + sizeof(struct ip_header);
  669.         tcb->mss = min(mtu,tcb->mss);
  670.     }
  671. }
  672.  
  673. /* Generate an initial sequence number and put a SYN on the send queue */
  674. void
  675. send_syn(tcb)
  676. register struct tcb *tcb;
  677. {
  678.     tcb->iss = iss();
  679.     tcb->rttseq = tcb->snd.ptr = tcb->snd.wl2 = tcb->snd.nxt = tcb->snd.una = tcb->iss;
  680.     tcb->sndcnt++;
  681.     tcb->force = 1;
  682. }
  683.  
  684. /* Add an entry to the resequencing queue in the proper place */
  685. static void
  686. add_reseq(tcb,tos,seg,bp,length)
  687. struct tcb *tcb;
  688. char tos;
  689. struct tcp_header *seg;
  690. struct mbuf *bp;
  691. int16 length;
  692. {
  693.     register struct reseq *rp,*rp1;
  694.     char *malloc();
  695.  
  696.     /* Allocate reassembly descriptor */
  697.     if((rp = (struct reseq *)malloc(sizeof (struct reseq))) == NULLRESEQ){
  698.         /* No space, toss on floor */
  699.         free_p(bp);
  700.         return;
  701.     }
  702.     bcopy((char *)seg,(char *)&rp->seg,sizeof(struct tcp_header));
  703.     rp->tos = tos;
  704.     rp->bp = bp;
  705.     rp->length = length;
  706.  
  707.     /* Place on reassembly list sorting by starting seq number */
  708.     rp1 = tcb->reseq;
  709.     if(rp1 == NULLRESEQ || seq_lt(seg->seq,rp1->seg.seq)){
  710.         /* Either the list is empty, or we're less than all other
  711.          * entries; insert at beginning.
  712.          */
  713.         rp->next = rp1;
  714.         tcb->reseq = rp;
  715.     } else {
  716.         /* Find the last entry less than us */
  717.         for(;;){
  718.             if(rp1->next == NULLRESEQ || seq_lt(seg->seq,rp1->next->seg.seq)){
  719.                 /* We belong just after this one */
  720.                 rp->next = rp1->next;
  721.                 rp1->next = rp;
  722.                 break;
  723.             }
  724.             rp1 = rp1->next;
  725.         }
  726.     }
  727. }
  728.  
  729. /* Fetch the first entry off the resequencing queue */
  730. static void
  731. get_reseq(tcb,tos,seg,bp,length)
  732. register struct tcb *tcb;
  733. char *tos;
  734. struct tcp_header *seg;
  735. struct mbuf **bp;
  736. int16 *length;
  737. {
  738.     register struct reseq *rp;
  739.  
  740.     if((rp = tcb->reseq) == NULLRESEQ)
  741.         return;
  742.  
  743.     tcb->reseq = rp->next;
  744.  
  745.     *tos = rp->tos;
  746.     bcopy((char *)&rp->seg,(char *)seg,sizeof(struct tcp_header));
  747.     *bp = rp->bp;
  748.     *length = rp->length;
  749.     free((char *)rp);
  750. }
  751.  
  752. /* Trim segment to fit window. Return 0 if OK, -1 if segment is
  753.  * unacceptable.
  754.  */
  755. static int
  756. trim(tcb,seg,bp,length)
  757. register struct tcb *tcb;
  758. register struct tcp_header *seg;
  759. struct mbuf **bp;
  760. int16 *length;
  761. {
  762.     struct mbuf *nbp;
  763.     long dupcnt,excess;
  764.     int16 len;        /* Segment length including flags */
  765.     char accept;
  766.  
  767.     accept = 0;
  768.     len = *length;
  769.     if(seg->flags & SYN)
  770.         len++;
  771.     if(seg->flags & FIN)
  772.         len++;
  773.  
  774.     /* Acceptability tests */
  775.     if(tcb->rcv.wnd == 0){
  776.         /* Only in-order, zero-length segments are acceptable when our window
  777.          * is closed.
  778.          */
  779.         if(seg->seq == tcb->rcv.nxt && len == 0){
  780.             return 0;    /* Acceptable, no trimming needed */
  781.         }
  782.     } else {
  783.         /* Some part of the segment must be in the window */
  784.         if(in_window(tcb,seg->seq)){
  785.             accept++;    /* Beginning is */
  786.         } else if(len != 0){
  787.             if(in_window(tcb,(int32)(seg->seq+len-1)) || /* End is */
  788.              seq_within(tcb->rcv.nxt,seg->seq,(int32)(seg->seq+len-1))){ /* Straddles */
  789.                 accept++;
  790.             }
  791.         }
  792.     }
  793.     if(!accept){
  794.         free_p(*bp);
  795.         return -1;
  796.     }
  797.     dupcnt = tcb->rcv.nxt - seg->seq;
  798.     if(dupcnt > 0){
  799.         /* Trim off SYN if present */
  800.         if(seg->flags & SYN){
  801.             /* SYN is before first data byte */
  802.             seg->flags &= ~SYN;
  803.             seg->seq++;
  804.             dupcnt--;
  805.         }
  806.         if(dupcnt > 0){
  807.             pullup(bp,NULLCHAR,(int16)dupcnt);
  808.             seg->seq += dupcnt;
  809.             *length -= dupcnt;
  810.         }
  811.     }
  812.     excess = seg->seq + *length - (tcb->rcv.nxt + tcb->rcv.wnd);
  813.     if(excess > 0){
  814.         /* Trim right edge */
  815.         *length -= excess;
  816.         nbp = copy_p(*bp,*length);
  817.         free_p(*bp);
  818.         *bp = nbp;
  819.         seg->flags &= ~FIN;    /* FIN follows last data byte */
  820.     }
  821.     return 0;
  822. }
  823.